#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Purpose: Project editor dialog
# Created: 02/04/2009
# $Id $
# Copyright (c) 2008,2009 by University College London
# Authors:
# Didrik Pinte --<dpinte@dipole-consulting.com>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with HydroPlatform for details.

import datetime
import sqlalchemy
import wx
import wx.calendar

from hydroplatform.model import network
from hydroplatform.model import units
from hydroplatform.model.networkfun import project_time_horizon_changed
from Thuban.UI import projdialog
from Thuban.UI.projlist import PROJ_SELECTION_CHANGED

from enthought.traits.api import HasTraits, Str, Date, Enum, Instance, \
   Property, cached_property, List, ListStr, Button, Any
from enthought.traits.ui.api import View, VGroup, HGroup, Item, Group, \
     Tabbed, ListEditor, CheckListEditor, EnumEditor, Handler
from enthought.traits.ui.menu import OKButton, CancelButton

class TraitedProjectEditorDialog(HasTraits):
   
   context = Any
   project = Any
   name = Str
   string_limit = Enum(25, 8)
   projection_str = Str("Undefined")
   projection_btn = Button(label="Change")
   from_date = Date()
   to_date = Date()
   punits = List(label="Units")
   
   sstep = Enum(units.MONTHLY, units.TIMESTEPS.keys(), label="Timestep")
   tsteps = Property(Str, label="Timestep")
   
   def __init__(self, **traits):
      HasTraits.__init__(self, **traits)
      '''
      Add a traits event monitor when the user adds or remove units
      '''
      self.name = self.project.name
      if self.project.horizon_from is None:
         self.from_date = datetime.date.today()
      else:
         self.from_date = self.project.horizon_from
      if self.project.horizon_to is None :
         diff = datetime.timedelta(days=1)
         self.to_date = datetime.date.today()+diff

      else:
         self.to_date = self.project.horizon_to
      if self.project.time_step is not None:
         self.sstep = self.project.time_step
      if self.project.GetProjection() is not None:
         self.projection_str = self.project.GetProjection().Label()
      self.on_trait_change(self.change_units_visiblity,
                           'punits.selected_units') 
      
   def change_units_visiblity(self, object, name, old, new):
      '''
      old are the list of unitcategories before the update
      new are the list of unitcategories after the udpdate
      
      Dirty way to do it : remove all the units for the old unitcategories and 
      create all the record for the units in the new unitcategories
      '''
      if self.traits_inited:
         dbsession = self.context.session.dbsession
         for unitcategory in old:
            for unitname in unitcategory.selected_units:
               unit = dbsession.query(units.Unit).filter(
                  sqlalchemy.and_(units.Unit.name==unitname, 
                                  units.Unit.category == unitcategory.name)).first()
               self.project.units.remove(unit)
         for unitcategory in new:
            for unitname in unitcategory.selected_units:
               unit = dbsession.query(units.Unit).filter(
                  sqlalchemy.and_(units.Unit.name==unitname, 
                                  units.Unit.category== unitcategory.name)).first()
               self.project.units.append(unit)
         return True

   
   @cached_property
   def _get_tsteps(self):
      valid_steps = dict()
      for key, val in units.TIMESTEPS.items():
            valid_steps[key] = val.name
      return valid_steps
  
   traits_view = View(
       Group(
          VGroup(
             Group(Item("name", width=150), 
                 "string_limit",
                 HGroup(Item("projection_str", style="readonly", width=150),
                        Item("projection_btn", show_label=False)), 
                   show_border = True)
             ),
             Group(
                   Item("from_date", style="simple"),
                   Item("to_date", style="simple"),
                   Item("sstep", editor=EnumEditor(name="tsteps")),
                   show_border = True
             ),
            label="Properties",
            show_border = False
          ),
       Group(
          Item('punits', editor=ListEditor(use_notebook = True,
                                          deletable    = False,
                                          page_name    =".name"),
               style      = "custom",
               show_label = False),
          label="Units"),
      title     = "Project editor",      
      buttons   = [OKButton, CancelButton],
      resizable = True
   )
   
   def _projection_btn_fired(self):
      '''
      When fired, open up the projection selection dialog
      Display the Thuban projection form. The dialog is linked to the project
      by using its setProjection method.
      '''
      pdialog = projdialog.ProjFrame(self.context.mainwindow, "projdialog", 
                                     "Unprojected", self.project)
      pdialog.projection_list.Subscribe(PROJ_SELECTION_CHANGED,
                                       self.OnProjChanged)
      pdialog.Show()      
   
   def OnProjChanged(self, projs):
      '''
      On projection change, updates the projection button label
      '''
      if len(projs) == 1:
         proj, projfile = projs[0]
         if proj is not None:
            self.projection_str = proj.Label()
   
class ProjectHandler(Handler):
   '''
   Manages what to do when the user has finished choosing the objects 
   he wants to import
   '''
   def close(self, info, is_ok):
      '''
      On close, transfer the needed link and node types 
      '''
      if is_ok:
         # should manage what has to be done --> thus, 
         # updating the project !         
         project = info.object.project
         project.name         = info.object.name
         project.limit_to_8   = (info.object.string_limit == 8)
         
         has_time_horizon_changed = False
         if (project.horizon_from != info.object.from_date) or \
            (project.horizon_to != info.object.to_date) or \
            (project.time_step != info.object.sstep):
            has_time_horizon_changed = True
            
         project.horizon_from = info.object.from_date 
         project.horizon_to   = info.object.to_date 
         project.time_step    = info.object.sstep
         tester = open('C:\Users\Hos\Desktop\Tester','a')
         tester.write( 'fromd = %s\ntod = %s\n' %(str(project.horizon_from),str(project.horizon_to)))
         
         # MARK
         # has_time_horizon_changed is correct at this point, so the if statement gets hit
         if has_time_horizon_changed is True :
            project_time_horizon_changed(project, \
                                         info.object.context.session.dbsession)
            # dates for nodes at this point are WRONG when they should be right...
            # import pdb; pdb.set_trace()
            tester.write('Inside the ProjectHandler class, within close(), date val is project.nodes[0] tod is = %s\n'% (str(project.nodes[0].type.fields[0].attribute_type.tod)) 


         
      return super(ProjectHandler, self).close(info, is_ok)
